import Autoprefixer from 'autoprefixer';
import { resolve } from 'path';
import type { UserConfig, UserConfigFn } from 'vite';
import { defineConfig, loadEnv, mergeConfig } from 'vite';

import { ASSET_DIR, TOKEN_PROXY } from './constants';
import { configVitePlugins } from './plugins';
import { createDir, getOptimizeDepIncludes, resolveProxy, wrapperEnv } from './utils';
import { type VitePWAOptions } from 'vite-plugin-pwa';
export type ViteConfig = Promise<UserConfig | UserConfigFn>;

export type ProConfig = {
  pwaCfg: Partial<VitePWAOptions>;
};

export async function createViteConfig (cwd: string, proConfig?: Partial<ProConfig>,
  proViteConfig?: Record<string, any>): Promise<UserConfig | UserConfigFn> {
  return defineConfig(async({ command, mode }) => {
    const root = cwd;
    
    const env = loadEnv(mode, root);
    const viteEnv = wrapperEnv(env);
    
    const {
      VITE_PROXY,
      VITE_PUBLIC_PATH,
      VITE_DROP_CONSOLE,
      VITE_USE_MORE_PAGE = true,
      VITE_AUTO_OPEN = true,
      VITE_USE_HTTPS = true,
      VITE_PROJECT_TYPE
    } = viteEnv;
    
    const isBuild = command === 'build';
    const _root = root.replace(/\\/g, '/');
    
    createDir(resolve(root, './types'));
    
    const commonServer = {
      open: VITE_AUTO_OPEN,
      port: 8888,
      https: VITE_USE_HTTPS,
      host: true
    };
    
    const server = VITE_USE_HTTPS
      ? commonServer
      : {
        ...commonServer,
        proxy: isBuild ? {} : resolveProxy(VITE_PROXY?.concat(TOKEN_PROXY))
      };
    
    const commonConfig: UserConfig = {
      root,
      base: VITE_PUBLIC_PATH,
      resolve: {
        alias: {
          '@/': `${resolve(root, 'src')}/`,
          '#/': `${resolve(root, 'types')}/`
        }
      },
      json: {
        namedExports: true,
        stringify: false
      },
      server,
      esbuild: {
        pure: VITE_DROP_CONSOLE ? ['console.log', 'debugger'] : []
      },
      css: {
        preprocessorOptions: {
          scss: {
            additionalData: '@import "src/styles/vars.scss";@import "./node_modules/@vc/styles/web/index.scss";@import "./node_modules/vc/src/styles/vars.scss";',
            javascriptEnabled: true
          }
        },
        postcss: {
          plugins: [Autoprefixer()]
        }
      },
      build: {
        assetsDir: ASSET_DIR,
        target: 'es2015',
        cssTarget: 'chrome61',
        outDir: 'dist',
        emptyOutDir: false,
        reportCompressedSize: false,
        assetsInlineLimit: 4096,
        cssCodeSplit: true,
        chunkSizeWarningLimit: 2048,
        rollupOptions: {
          output: {
            manualChunks: {
              vue: ['vue', 'pinia', 'vue-router', '@vue/shared'],
              echarts: ['echarts'],
            },
            entryFileNames: `${ASSET_DIR}/js/[name]-[hash].js`,
            chunkFileNames: `${ASSET_DIR}/chunk/[name]-[hash].js`,
            assetFileNames: `${ASSET_DIR}/[name]-[hash].[ext]`
          }
        }
      },
      optimizeDeps: {
        include: getOptimizeDepIncludes(VITE_PROJECT_TYPE, VITE_USE_MORE_PAGE),
        exclude: ['vue-demi']
      },
      plugins: await configVitePlugins(root, viteEnv, isBuild, proConfig)
    };
    
    return mergeConfig(commonConfig, proViteConfig as Record<string, any>);
  });
}
